home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
mxcode
/
jmp
/
modplay.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-29
|
5KB
|
174 lines
#include <dos.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "modplay.h"
#include "device.h"
void fillbuffer(uchar *);
void worknote(note *, channel *);
module song;
char * sampledata[31];
note * patterndata[64];
char buffer[2][2500];
uint playrate;
uint tablepos;
uint patternpos;
ulong patternticks;
ulong patternticksaim;
ulong sampleticksconst;
channel channels[4];
int
modload(char * filename)
{
uint i, j, max;
uchar a, b, c;
sample *sptr;
FILE *fp;
if ((fp = fopen(filename, "rb")) == NULL) return 0;
if (fread(&(song.title), 1, 1084, fp) != 1084) return 0;
if (memcmp(&(song.signature), "M.K.", 4) != 0 &&
memcmp(&(song.signature), "FLT4", 4) != 0 &&
memcmp(&(song.signature), "FLT8", 4) != 0) {
memcpy(&(song.signature), "M.K.", 4);
memcpy(&(song.length), &(song.samples[15]), 130);
memset(&(song.samples[15]), 0, 480);
if (fseek(fp, 600L, SEEK_SET) != 0) return 0;
}
for (i = max = 0; i < 128; i++)
while (max <= song.patterntable[i]) {
if ((patterndata[max]=malloc(1024))==NULL) return 0;
if (fread(patterndata[max++],1024,1,fp)!=1) return 0;
}
for (i = 0, sptr = song.samples; i < 31; i++, sptr++) {
_AX = sptr->length; asm {xchg ah, al}; sptr->length = _AX * 2;
_AX = sptr->reppnt; asm {xchg ah, al}; sptr->reppnt = _AX * 2;
_AX = sptr->replen; asm {xchg ah, al}; sptr->replen = _AX * 2;
if (sptr->length == 0) continue;
if ((sampledata[i] = malloc(sptr->length)) == NULL) return 0;
fread(sampledata[i], sptr->length, 1, fp);
if (sptr->replen + sptr->reppnt > sptr->length)
sptr->replen = sptr->length - sptr->reppnt;
for (max = 0; max < sptr->length; max++)
sampledata[i][max] ^= 0x80;
}
return 1;
}
int
modinit(int frequency)
{
if ((sbinit(0x220, 7, 1) == 0)) return 0;
if ((playrate = sbrate(frequency)) == 0) return 0;
return playrate;
}
int
modplay(void)
{
tablepos = 0;
patternpos = 0;
patternticks = 6L * playrate / 51 + 1;
patternticksaim = 6L * playrate / 51;
sampleticksconst = 3445744UL / playrate;
channels[0].volume = 0; channels[0].period = 448;
channels[1].volume = 0; channels[1].period = 448;
channels[2].volume = 0; channels[2].period = 448;
channels[3].volume = 0; channels[3].period = 448;
fillbuffer(buffer[0]);
fillbuffer(buffer[1]);
sbdblbuf(buffer[0], 2500, buffer[1], 2500);
return 1;
}
int
modpoll(void)
{
if (tablepos > song.length) {
return 1;
} else if (bufoverlap) {
return 2;
} else if (bufempty[bufplaying^1]) {
bufempty[bufplaying^1] = 0;
fillbuffer(buffer[bufplaying^1]);
return 0;
} else
return 0;
}
int
modstop(void)
{
sbstop();
return 0;
}
void
fillbuffer(uchar * buffer)
{
uint i, j, k, l;
note *nptr;
channel *cptr;
for (i = 0; i < 2500; i++) {
if (patternticks++ > patternticksaim) {
nptr = patterndata[song.patterntable[tablepos]];
nptr = nptr + patternpos;
cptr = channels;
patternpos += 4;
patternticks = 0;
worknote(nptr+0, cptr+0);
worknote(nptr+1, cptr+1);
worknote(nptr+2, cptr+2);
worknote(nptr+3, cptr+3);
if (patternpos == 256) {
tablepos++;
patternpos = 0;
}
}
for (j = l = 0, cptr = channels; j < 4; j++, cptr++) {
k = sampleticksconst * cptr->ticks++ / cptr->period;
if (k > cptr->length) {
cptr->sampdata += cptr->reppnt;
cptr->length = cptr->replen;
cptr->reppnt = 0;
cptr->ticks = 0;
l += cptr->sampdata[0] * cptr->volume;
} else
l += cptr->sampdata[k] * cptr->volume;
}
buffer[i] = l / 256;
}
}
void
worknote(note * nptr, channel * cptr)
{
uint sample, period, effect;
sample = (nptr->sampperiod & 0xF0) | (nptr->sampeffect >> 4);
period = ((nptr->sampperiod & 0xF) << 8) | nptr->period;
effect = ((nptr->sampeffect & 0xF) << 8) | nptr->effect;
if (period != 0) {
if (sample != 0) cptr->sampnum = --sample;
cptr->sampdata = sampledata[cptr->sampnum];
cptr->length = song.samples[cptr->sampnum].length;
cptr->reppnt = song.samples[cptr->sampnum].reppnt;
cptr->replen = song.samples[cptr->sampnum].replen;
cptr->volume = song.samples[cptr->sampnum].volume;
cptr->period = period;
cptr->ticks = 0;
}
switch (effect >> 8) {
case 0xF: patternticksaim=(long)(effect&0xFF)*playrate/51;break;
case 0xD: patternpos = (effect & 0xFF) * 4; tablepos++; break;
case 0xC: cptr->volume = (effect & 0xFF); break;
case 0xB: tablepos = (effect & 0xFF); break;
case 0x9: cptr->sampdata += (effect & 0xFF) * 256; break;
}
}